class Aether3D{
  // Speeds
  int l01,l02,l03,l04,l05,l06,l07,l08,l09,l10,l11,l12;
  // Size
  int s01,s02,s03,s04,s05,s06,s07,s08,s09,s10,s11,s12;
  // Position
  int p01,p02,p03,p04,p05,p06,p07,p08,p09,p10,p11,p12;

  Aether3D(){
    randInit();
  }

  void drawAether(int u, int v){
    colorMode(HSB,255);
    for (int i=0; i<u; i++){
      // Move Control Points
      float t = frameCount*0.25 + ((float)i*75.0)/(float)u;
      float w = frameCount*0.25 + ((float)(i+1)*75.0)/(float)u;
      // Create parametric position
      float Ax1 = (sin(t*d2r*l01*0.1) * s01) + p01;
      float Ay1 = (sin(t*d2r*l02*0.1) * s02) + p02;
      float Az1 = (sin(t*d2r*l03*0.1) * s03) + p03;
      float Bx1 = (sin(t*d2r*l04*0.1) * s04) + p04;
      float By1 = (sin(t*d2r*l05*0.1) * s05) + p05;
      float Bz1 = (sin(t*d2r*l06*0.1) * s06) + p06;
      float Cx1 = (sin(t*d2r*l07*0.1) * s07) + p07;
      float Cy1 = (sin(t*d2r*l08*0.1) * s08) + p08;
      float Cz1 = (sin(t*d2r*l09*0.1) * s09) + p09;
      float Dx1 = (sin(t*d2r*l10*0.1) * s10) + p10;
      float Dy1 = (sin(t*d2r*l11*0.1) * s11) + p11;
      float Dz1 = (sin(t*d2r*l12*0.1) * s12) + p12;
      float Ax2 = (sin(w*d2r*l01*0.1) * s01) + p01;
      float Ay2 = (sin(w*d2r*l02*0.1) * s02) + p02;
      float Az2 = (sin(w*d2r*l03*0.1) * s03) + p03;
      float Bx2 = (sin(w*d2r*l04*0.1) * s04) + p04;
      float By2 = (sin(w*d2r*l05*0.1) * s05) + p05;
      float Bz2 = (sin(w*d2r*l06*0.1) * s06) + p06;
      float Cx2 = (sin(w*d2r*l07*0.1) * s07) + p07;
      float Cy2 = (sin(w*d2r*l08*0.1) * s08) + p08;
      float Cz2 = (sin(w*d2r*l09*0.1) * s09) + p09;
      float Dx2 = (sin(w*d2r*l10*0.1) * s10) + p10;
      float Dy2 = (sin(w*d2r*l11*0.1) * s11) + p11;
      float Dz2 = (sin(w*d2r*l12*0.1) * s12) + p12;
      for (int j=0; j<v; j++){
        float f = (float)j/(float)v;
        float h = (float)(j+1)/(float)v;

        float x11 = BezierVal(Ax1,Bx1,Cx1,Dx1,f);
        float x12 = BezierVal(Ax1,Bx1,Cx1,Dx1,h);
        float x21 = BezierVal(Ax2,Bx2,Cx2,Dx2,f);
        float x22 = BezierVal(Ax2,Bx2,Cx2,Dx2,h);
        float y11 = BezierVal(Ay1,By1,Cy1,Dy1,f);
        float y12 = BezierVal(Ay1,By1,Cy1,Dy1,h);
        float y21 = BezierVal(Ay2,By2,Cy2,Dy2,f);
        float y22 = BezierVal(Ay2,By2,Cy2,Dy2,h);
        float z11 = BezierVal(Az1,Bz1,Cz1,Dz1,f);
        float z12 = BezierVal(Az1,Bz1,Cz1,Dz1,h);
        float z21 = BezierVal(Az2,Bz2,Cz2,Dz2,f);
        float z22 = BezierVal(Az2,Bz2,Cz2,Dz2,h);
        // create quad
        beginShape(QUADS);
        float hval;
        if (!sunflow){
          hval = ((int)t*2)%255;
          fill(hval,200,250);
        }
        vertex(x11,y11,z11);
        vertex(x12,y12,z12);
        if (!sunflow){
          hval = ((int)w*2)%255;
          fill(hval,200,250);
        }
        vertex(x22,y22,z22);
        vertex(x21,y21,z21);
        endShape();
      }
    }
  }

  void randInit(){
    // randomize 
    randomSeed(SEED);

    // Speeds
    l01 = round(random(100));
    l02 = round(random(100));
    l03 = round(random(100));
    l04 = round(random(100));
    l05 = round(random(100));
    l06 = round(random(100));
    l07 = round(random(100));
    l08 = round(random(100));
    l09 = round(random(100));
    l10 = round(random(100));
    l11 = round(random(100));
    l12 = round(random(100));
    // Size
    s01 = round(random(width/32,width/3));
    s02 = round(random(width/32,width/3));
    s03 = round(random(width/32,width/3));
    s04 = round(random(width/32,width/3));
    s05 = round(random(width/32,width/3));
    s06 = round(random(width/32,width/3));
    s07 = round(random(width/32,width/3));
    s08 = round(random(width/32,width/3));
    s09 = round(random(width/32,width/3));
    s10 = round(random(width/32,width/3));
    s11 = round(random(width/32,width/3));
    s12 = round(random(width/32,width/3));
    // Position
    p01 = round(random(-width*0.5, width*0.5));
    p02 = round(random(-width*0.5, width*0.5));
    p03 = round(random(-width*0.5, width*0.5));
    p04 = round(random(-width*0.50, width*0.5));
    p05 = round(random(-width*0.50, width*0.5));
    p06 = round(random(-width*0.50, width*0.5));
    p07 = round(random(-width*0.50, width*0.5));
    p08 = round(random(-width*0.50, width*0.5));
    p09 = round(random(-width*0.50, width*0.5));
    p10 = round(random(-width*0.50, width*0.5));
    p11 = round(random(-width*0.50, width*0.5));
    p12 = round(random(-width*0.50, width*0.5));
  }
}

float BezierVal(float a, float b, float c, float d, float t){
  float w = 1-t;

  float m = (t*a) + (w*b);
  float n = (t*b) + (w*c);
  float o = (t*c) + (w*d);

  float p = (t*m) + (w*n);
  float q = (t*n) + (w*o);
  return (t*p) + (w*q);
}
